home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Camelot
/
Camelot 078 (1990-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip
/
Camelot 078 (1990-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf
/
MSH
/
src
/
hanmain.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-17
|
10KB
|
451 lines
/*-
* $Id: hanmain.c,v 1.30 90/06/04 23:16:50 Rhialto Rel $
* $Log: hanmain.c,v $
* Revision 1.30 90/06/04 23:16:50 Rhialto
* Release 1 Patch 3
*
* HANMAIN.C
*
* The code for the messydos file system handler.
*
* Some start/stop stuff that is not really part of the
* file system itself but that must be done anyway.
*
* This code is (C) Copyright 1989 by Olaf Seibert. All rights reserved. May
* not be used or copied without a licence.
-*/
#include "dos.h"
#include "han.h"
#ifdef HDEBUG
# define debug(x) dbprintf x
#else
# define debug(x)
#endif
extern int CheckBootBlock;
extern char DotDot[1 + 8 + 3];
struct Library *IntuitionBase;
static char RCSId[] = "Messydos filing system $Revision: 1.30 $ $Date: 90/06/04 23:16:50 $, by Olaf Seibert";
byte
ToUpper(ch)
register byte ch;
{
if (ch >= 'a' && ch <= 'z')
return ch + ('A' - 'a');
if (ch == '.')
return '!';
return ch & ~DIR_DELETED_MASK;
}
long
lmin(a, b)
long a,
b;
{
return (a < b) ? a : b;
}
byte *
ZapSpaces(begin, end)
register byte *begin,
*end;
{
while (end > begin && end[-1] == ' ')
*--end = '\0';
return end;
}
/*
* Map an arbitrary file name to MS-DOS conventions. The output format is
* 8+3 without dot, padded with spaces, suitable for direct comparison
* with directory entries. Return a pointer to the delimiter found ('\0'
* or '/'). [[Make sure that Examine/ExNext return a proper inverse of
* this...]]
*/
byte *
ToMSName(dest, source)
byte *dest;
register byte *source;
{
byte *dotp;
byte *slashp;
register int i,
len;
if (*source == '/') { /* parentdir */
strncpy(dest, DotDot, 8 + 3); /* ".." */
return source;
}
/*
* Remove any strictly leading dots. .info -> info, .indent.pro ->
* indent.pro, .profile -> profile, etc.
*/
while (*source == '.')
source++;
/*
* Find dot and slash which are delimiters of name and extension.
*/
{
register byte *cp;
cp = source;
while (*cp) {
if (*cp == '.' || *cp == '/')
break;
cp++;
}
dotp = cp;
while (*cp) {
if (*cp == '/')
break;
cp++;
}
slashp = cp;
}
len = dotp - source;
if (len > 8)
len = 8;
for (i = 0; i < len; i++) {
*dest++ = ToUpper(*source++);
}
for (; i < 8; i++) {
*dest++ = ' ';
}
source = dotp + 1;
len = slashp - source; /* so will be -1 if no suffix */
if (len > 3)
len = 3;
for (i = 0; i < len; i++) {
*dest++ = ToUpper(*source++);
}
for (; i < 3; i++) {
*dest++ = ' ';
}
return slashp;
}
/*
* Do the Info call.
*/
long
MSDiskInfo(infodata)
struct InfoData *infodata;
{
extern DEVLIST *VolNode;
setmem(infodata, sizeof (*infodata), 0);
infodata->id_DiskState = IDDiskState;
infodata->id_DiskType = IDDiskType;
infodata->id_UnitNumber = UnitNr;
infodata->id_VolumeNode = (BPTR) CTOB(VolNode);
infodata->id_InUse = LockList ? 1 : 0;
if (IDDiskType == ID_DOS_DISK) {
infodata->id_NumBlocks = Disk.nsects;
infodata->id_NumBlocksUsed = Disk.nsects - Disk.nsectsfree;
infodata->id_BytesPerBlock = Disk.bps;
}
return DOSTRUE;
}
/*
* We (re-)establish our List of MSFileLocks after a disk has been
* (re-)inserted. If there are no known locks, we make the root lock from
* the volume label, if there is one.
*
* We get a special cookie to hand to a cleanup routine that we must call
* when finally all locks on the current disk are UnLock()ed. (this is
* actually the volume node, but we don't want to know that.)
*
* This must be called some time after IdentifyDisk().
*/
void
MSDiskInserted(locks, cookie)
register struct LockList **locks;
void *cookie;
{
debug(("MSDiskInserted %08lx\n", cookie));
LockList = *locks;
if (LockList == NULL) {
LockList = NewLockList(cookie);
RootLock = MakeLock(NULL, &Disk.vollabel, SHARED_LOCK);
} else {
RootLock = MSDupLock(GetTail(&LockList->ll_List));
}
InitCacheList();
}
/*
* Remove the current disk. A place is offered to save the current
* LockList to restore later. We must unlock the root lock since it isn't
* a real reference to the disk, just a placeholder for dummies that hand
* us NULL locks.
*/
int
MSDiskRemoved(locks)
register struct LockList **locks;
{
#ifndef READONLY
if (FatDirty || (DelayState & DELAY_DIRTY))
MSUpdate(1); /* Force a requester */
#endif
FreeFat();
FreeCacheList();
IDDiskType = ID_NO_DISK_PRESENT;
*locks = NULL;
if (RootLock == NULL) {
debug(("MSDiskRemoved with no RootLock\n"));
return 1;
}
#ifdef HDEBUG
if (RootLock != GetTail(&LockList->ll_List)) {
debug(("RootLock not at end of LockList!\n"));
/* Get the lock on the root dir at the tail of the List */
Remove(RootLock);
AddTail(&LockList->ll_List, RootLock);
}
#endif
/*
* If there are no real locks on the disk, we need not keep any
* information about it.
*/
MSUnLock(RootLock); /* may call FreeLockList and free VolNode
* (!) */
RootLock = NULL;
if (LockList) {
*locks = LockList; /* VolNode can't be gone now... */
LockList = NULL;
return 0; /* not all references gone */
} else {
return 1; /* all gone, even the VolNode */
}
}
void
HanCloseDown()
{
#ifdef HDEBUG
register struct MSFileLock *fl;
while (LockList && (fl = (struct MSFileLock *) GetHead(&LockList->ll_List))) {
debug(("UNLOCKING %08lx: ", fl));
PrintDirEntry(&fl->msfl_Msd);
MSUnLock(fl); /* Remove()s it from this List */
}
#endif
if (DiskIOReq) {
if (DiskIOReq->iotd_Req.io_Unit) {
MSUpdate(1);
CloseDevice(DiskIOReq);
}
DeleteExtIO(DiskIOReq);
DiskIOReq = NULL;
}
if (TimeIOReq) {
if (TimeIOReq->tr_node.io_Unit) {
WaitIO(TimeIOReq);
CloseDevice(TimeIOReq);
}
DeleteExtIO(TimeIOReq);
TimeIOReq = NULL;
}
if (DiskReplyPort) {
DeletePort(DiskReplyPort);
DiskReplyPort = NULL;
}
if (IntuitionBase) {
CloseLibrary(IntuitionBase);
IntuitionBase = NULL;
}
}
int
HanOpenUp()
{
LockList = NULL;
RootLock = NULL;
Fat = NULL;
IDDiskState = ID_WRITE_PROTECTED;
IDDiskType = ID_NO_DISK_PRESENT;
DelayState = DELAY_OFF;
Disk.bps = MS_BPS;
CheckBootBlock = 1;
InitCacheList();
TimeIOReq = NULL;
#ifdef HDEBUG
if (!(DiskReplyPort = CreatePort("MSH:disk.replyport", -1L)))
goto abort;
#else
if (!(DiskReplyPort = CreatePort(NULL, -1L)))
goto abort;
#endif
debug(("DiskReplyPort = 0x%08lx\n", DiskReplyPort));
if (!(DiskIOReq = CreateExtIO(DiskReplyPort, (long) sizeof (*DiskIOReq)))) {
debug(("Failed to CreateExtIO\n"));
goto abort;
}
if (OpenDevice(DevName, UnitNr, DiskIOReq, DevFlags | TDF_ALLOW_NON_3_5)) {
debug(("Failed to OpenDevice\n"));
goto abort;
}
TimeIOReq = (struct timerequest *) CreateExtIO(DiskReplyPort,
(long) sizeof (*TimeIOReq));
if (TimeIOReq == NULL || OpenDevice(TIMERNAME, UNIT_VBLANK, TimeIOReq, 0L))
goto abort;
TimeIOReq->tr_node.io_Flags = IOF_QUICK; /* For the first WaitIO() */
IntuitionBase = OpenLibrary("intuition.library", 0L);
return DOSTRUE;
abort:
HanCloseDown();
return 0;
}
/*
* Relabel the disk. We create new labels if necessary.
*/
long
MSRelabel(newname)
byte *newname;
{
#ifdef READONLY
return DOSFALSE;
#else
/*
* A null or empty string means: remove the label, if any.
*/
if (!newname || !*newname) {
if ((int) RootLock->msfl_DirSector >= (int) Disk.rootdir) {
RootLock->msfl_Msd.msd_Name[0] = DIR_DELETED;
RootLock->msfl_Msd.msd_Attributes = 0;
WriteFileLock(RootLock);
RootLock->msfl_Msd = FakeRootDirEntry.de_Msd;
RootLock->msfl_DirSector = -1;
Disk.vollabel = FakeRootDirEntry;
}
return DOSTRUE;
}
/*
* No label yet? Then we must create one, even if we need to move
* something else for it.
*/
if ((int) RootLock->msfl_DirSector < 0) {
struct MSFileLock *new;
new = MSLock(RootLock, "><>.\\", EXCLUSIVE_LOCK ^ MODE_CREATEFILE);
if ((new == NULL) && (new = EmptyFileLock)) {
error = 0;
if (new->msfl_DirSector == Disk.rootdir) {
RootLock->msfl_DirSector = Disk.rootdir;
RootLock->msfl_DirOffset = new->msfl_DirOffset;
} else {
/*
* Move something out of the first directory block. Try
* not to move system files or directories (. ..), but
* we'll do it if we need to. Set the root dir date to
* now.
*/
byte *fromsec;
byte *tosec;
register struct MsDirEntry *dir;
fromsec = GetSec(Disk.rootdir);
tosec = GetSec(new->msfl_DirSector);
dir = (struct MsDirEntry *) fromsec;
while (dir->msd_Attributes & (ATTR_SYSTEM | ATTR_DIRECTORY)) {
if ((byte *) ++dir >= fromsec + Disk.bps) {
--dir; /* Back to last entry in the block */
break; /* and move it no matter what */
}
}
CopyMem(dir, tosec + new->msfl_DirOffset,
(long) sizeof (struct MsDirEntry));
MarkSecDirty(tosec);
RootLock->msfl_DirSector = Disk.rootdir;
RootLock->msfl_DirOffset = (byte *) dir - fromsec;
FreeSec(tosec);
FreeSec(fromsec);
}
}
EmptyFileLock = NULL;
MSUnLock(new);
}
if ((int) RootLock->msfl_DirSector >= Disk.rootdir) {
struct DateStamp dateStamp;
/*
* The easy part: Copy the name to Disk.vollabel and RootLock.
*/
{
register int i;
register byte *s,
*d;
s = newname;
d = Disk.vollabel.de_Msd.msd_Name;
for (i = 0; i < 8 + 3; i++) {
if (s[0])
*d++ = ToUpper(*s++);
else
*d++ = ' ';
}
}
DateStamp(&dateStamp);
ToMSDate(&Disk.vollabel.de_Msd.msd_Date,
&Disk.vollabel.de_Msd.msd_Time, &dateStamp);
RootLock->msfl_Msd = Disk.vollabel.de_Msd; /* Just for the name and
* date */
WriteFileLock(RootLock);
return DOSTRUE;
}
return DOSFALSE;
#endif
}
#ifdef HDEBUG
_abort()
{
HanCloseDown();
RemTask(NULL);
}
#endif /* HDEBUG */